﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using V2TEK.NET.SH.Silverlight.Charts.GanttHelper;
using System.Windows.Controls.Primitives;
using V2TEK.NET.SH.Silverlight.Charts.Core.Schedule;
using System.Collections.ObjectModel;
using System.Windows.Data;
using V2TEK.NET.SH.Silverlight.Charts.Core;
using System.ComponentModel;
using System.Collections.Specialized;

namespace V2TEK.NET.SH.Silverlight.Charts
{
    /// <summary>
    /// 横纵滚动条并甘特图(横道图)以及尚未实现的背景，如纵向时间分割线，横向条目分割线、关联关系等
    /// 本控件可以脱离Gantt独立运行
    /// </summary>
    public class GanttPanel : Core.Chart, INotifyPropertyChanged
    {
        private Type _taskEntryLayoutProvider = typeof(SimpleTaskEntryLayout);

        private EntryAction _teAction;
        private double _left = 0d;

        public static DependencyProperty ContentHeightProperty = DependencyProperty.Register("ContentHeight", typeof(double), typeof(GanttPanel), new PropertyMetadata(20d));
        public static DependencyProperty ContentWidthProperty = DependencyProperty.Register("ContentWidth", typeof(double), typeof(GanttPanel), new PropertyMetadata(5000d, new PropertyChangedCallback(PropertyChangeCallBack)));
        public static DependencyProperty ViewPortHeightProperty = DependencyProperty.Register("ViewPortHeight", typeof(double), typeof(GanttPanel), new PropertyMetadata(0d, new PropertyChangedCallback(PropertyChangeCallBack)));
        public static DependencyProperty ViewPortWidthProperty = DependencyProperty.Register("ViewPortWidth", typeof(double), typeof(GanttPanel), new PropertyMetadata(1000d));
        public static DependencyProperty RowHeightProperty = DependencyProperty.Register("RowHeight", typeof(double), typeof(GanttPanel), new PropertyMetadata(20d));

        public static DependencyProperty XPositionProperty = DependencyProperty.Register("XPosition", typeof(double), typeof(GanttPanel), new PropertyMetadata(0d));
        public static DependencyProperty YPositionProperty = DependencyProperty.Register("YPosition", typeof(double), typeof(GanttPanel), new PropertyMetadata(0d,new PropertyChangedCallback(PropertyChangeCallBack)));

        public static DependencyProperty StartDateProperty = DependencyProperty.Register("StartDate", typeof(DateTime), typeof(GanttPanel), new PropertyMetadata(DateTime.Now));
        public static DependencyProperty EndDateProperty = DependencyProperty.Register("EndDate", typeof(DateTime), typeof(GanttPanel), new PropertyMetadata(DateTime.Now.AddMonths(1)));
        public static DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource", typeof(object), typeof(GanttPanel),
            new PropertyMetadata(default(object), new PropertyChangedCallback(DataSourceChanged)));

        public static DependencyProperty TaskEntryLayoutProperty = DependencyProperty.Register("TaskEntryLayout", typeof(AbstractTaskEntryLayout), typeof(GanttPanel), null);
        public static readonly DependencyProperty ExpandLevelProperty = DependencyProperty.Register("ExpandLevel", typeof(int), typeof(GanttPanel), new PropertyMetadata(1));
        public static readonly DependencyProperty MaxHScrollDurationProperty = DependencyProperty.Register("MaxHScrollDuration", typeof(double), typeof(GanttPanel), null);
        public static readonly DependencyProperty MinDateTimeRangeWidthProperty = DependencyProperty.Register("MinDateTimeRangeWidth", typeof(double), typeof(GanttPanel), new PropertyMetadata(80d));

        public event EventHandler<OnMoveEventArgs> HorizontalMoveEnd;
        /// <summary>
        /// 纵向移动时，激发此事件
        /// </summary>
        public event EventHandler<OnMoveEventArgs> VerticalMove;
        public event EventHandler<OnMoveEventArgs> HorizontalMove;

        public GanttPanel()
        {
            this.DefaultStyleKey = typeof(GanttPanel);

            _teAction = EntryAction.LayoutUpdate;
            _left = 0d;

            if (MaxHScrollDuration == 0d)
                MaxHScrollDuration = 2 * ViewPortWidth;

            BindTaskEntryLayout();

            //Binding bhv = new Binding("XPosition");
            //bvpw.Converter = new XPToHSVConverter();
            //bvpw.ConverterParameter = this.TaskEntryLayout.Zoom;
            //bhv.Source = this;
            //bhv.Mode = BindingMode.OneTime;
            //this.HorizontalScrollBar.SetBinding(ScrollBar.ValueProperty, bhv)

            this.Loaded += new RoutedEventHandler(GanttPanel_Loaded);
            this.SizeChanged += new SizeChangedEventHandler(GanttPanel_SizeChanged);
        }

        private void BindTaskEntryLayout()
        {
            if (this.TaskEntryViewer != null && this.TaskEntryLayout != null)
            {
                this.TaskEntryLayout.ZoomChanged -= new EventHandler<PropertyChangeArgsWithValue<double>>(TaskEntryLayout_ZoomChanged);
                this.TaskEntryLayout.OnLayoutUpdate -= new LayoutUpdate(this.TaskEntryViewer.OnUpdate);
                this.TaskEntryLayout.OnLayoutUpdate -= new LayoutUpdate(TaskEntryLayout_OnLayoutUpdate);
                this.TaskEntryLayout.BatchRowsChanged -= new EventHandler(TaskEntryLayout_BatchRowsChanged);
                this.TaskEntryLayout.PropertyChanged -= new PropertyChangedEventHandler(TaskEntryLayout_PropertyChanged);
            }

            if (this.TaskEntryLayoutProvider == null)
                return;
            this.TaskEntryLayout = Activator.CreateInstance(this.TaskEntryLayoutProvider) as AbstractTaskEntryLayout;

            if (this.TaskEntryViewer != null)
            {
                this.TaskEntryLayout.ZoomChanged += new EventHandler<PropertyChangeArgsWithValue<double>>(TaskEntryLayout_ZoomChanged);
                this.TaskEntryLayout.OnLayoutUpdate += new LayoutUpdate(this.TaskEntryViewer.OnUpdate);
                this.TaskEntryLayout.OnLayoutUpdate += new LayoutUpdate(TaskEntryLayout_OnLayoutUpdate);
                this.TaskEntryLayout.BatchRowsChanged += new EventHandler(TaskEntryLayout_BatchRowsChanged);
                this.TaskEntryLayout.PropertyChanged += new PropertyChangedEventHandler(TaskEntryLayout_PropertyChanged);
            }

            Binding bstart = new Binding("StartDate");
            bstart.Source = this;
            bstart.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.StartDateProperty, bstart);

            Binding bend = new Binding("EndDate");
            bend.Source = this;
            bend.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.EndDateProperty, bend);

            Binding bx = new Binding("XPosition");
            bx.Source = this;
            //bx.Converter = new GPVXoTVXConverter();
            //bx.ConverterParameter = this.MaxHScrollDuration * this.EndDate.Subtract(this.StartDate).TotalMilliseconds / this.ContentWidth;
            bx.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.XPositionProperty, bx);

            Binding by = new Binding("YPosition");
            by.Source = this;
            by.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.YPositionProperty, by);


            Binding bch = new Binding("ContentHeight");
            bch.Source = this;
            bch.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.ContentHeightProperty, bch);

            Binding bcw = new Binding("ContentWidth");
            bcw.Source = this;
            bcw.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.ContentWidthProperty, bcw);

            Binding bvph = new Binding("ViewPortHeight");
            bvph.Source = this;
            bvph.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.ViewPortHeightProperty, bvph);

            Binding bvpw = new Binding("ViewPortWidth");
            bvpw.Converter = new GPVToTVVConverter();
            bvpw.ConverterParameter = this.MaxHScrollDuration;
            bvpw.Source = this;
            bvpw.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.ViewPortWidthProperty, bvpw);

            Binding brh = new Binding("RowHeight");
            brh.Source = this;
            brh.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.RowHeightProperty, brh);

            Binding bds = new Binding("DataSource");
            bds.Source = this;
            bds.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.DataSourceProperty, bds);

            Binding bel = new Binding("ExpandLevel");
            bel.Source = this;
            bel.Mode = BindingMode.OneWay;
            this.TaskEntryLayout.SetBinding(AbstractTaskEntryLayout.ExpandLevelProperty, bel);
        }

        void GanttPanel_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            RefreshHorizontalScrollBar(this.ContentWidth);
        }

        void GanttPanel_Loaded(object sender, RoutedEventArgs e)
        {
            RefreshHorizontalScrollBar(this.ContentWidth);
        }

        protected static void PropertyChangeCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            GanttPanel g = sender as GanttPanel;
            //AbstractTaskEntryLayout l = g.TaskEntryLayout;
            //if (args.Property.Equals(YPositionProperty))
            //{
            //    if (l != null)
            //    {
            //        double maxY = l.MaxY;
            //        if ((double)args.NewValue > maxY)
            //            g.YPosition = maxY;


            //        if (g.YPosition > 0d)
            //        {
            //            //缺失的Row高度
            //            double remainder = l.RowHeight - ((l.ViewPortHeight - g.HScrollBarHeight) % l.RowHeight);
            //            //if (remainder * 2 < l.RowHeight)
            //                g.TaskEntryViewer.BottomDelta = remainder;
            //            //else
            //            //    g.TaskEntryViewer.BottomDelta = remainder + l.RowHeight;
            //        }
            //        //else if((double)args.OldValue > 0d && g.YPosition > 0d)
            //        //{
            //        //    double remainder = (l.ViewPortHeight - g.HScrollBarHeight) % l.RowHeight;
            //        //    g.TaskEntryViewer.BottomDelta = -remainder;
            //        //}
            //        else if (g.YPosition == 0d)//滚动到最上面
            //        {
            //            g.TaskEntryViewer.BottomDelta = 0d;
            //        }
            //        //else//滚动到最下面
            //        //{
            //        //    double remainder = (l.ViewPortHeight - g.HScrollBarHeight) % l.RowHeight;
            //        //    if (remainder * 2 < l.RowHeight)
            //        //        g.TaskEntryViewer.BottomDelta = -remainder;
            //        //    else
            //        //        g.TaskEntryViewer.BottomDelta = -remainder + l.RowHeight;
            //        //}
            //    }
            //}

            //if (args.Property.Equals(ContentWidthProperty))
            //{
            //    if (g.HorizontalScrollBar != null)
            //    {
            //        g.RefreshHorizontalScrollBar((double)args.NewValue);
            //    }
            //}
               
        }
        private void RefreshHorizontalScrollBar(double contentWidth)
        {
            if (this.HorizontalScrollBar != null)
            {
                this.HorizontalScrollBar.SmallChange = this.ActualWidth * 0.2;
                this.HorizontalScrollBar.LargeChange = this.ActualWidth * 0.8;
            }
        }

        private Type mTaskRendererProvider = typeof(SimpleTaskEntryRenderer);
        public Type TaskRendererProvider
        {
            get
            {
                return mTaskRendererProvider;
            }
            set
            {
                if (mTaskRendererProvider != value)
                {
                    mTaskRendererProvider = value;

                    if (this.TaskEntryViewer != null)
                        this.TaskEntryViewer.TaskRendererProvider = TaskRendererProvider;
                }
            }
        }

        public int ExpandLevel
        {
            get
            {
                return (int)GetValue(ExpandLevelProperty);
            }
            set
            {
                SetValue(ExpandLevelProperty, value);
            }
        }

        public double MinDateTimeRangeWidth
        {
            get
            {
                return (double)GetValue(MinDateTimeRangeWidthProperty);
            }
            set
            {
                SetValue(MinDateTimeRangeWidthProperty, value);
            }
        }

        public object DataSource
        {
            get 
            {
                return GetValue(DataSourceProperty);
            }
            set
            {
                SetValue(DataSourceProperty, value);
            }
        }

        protected static void DataSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is GanttPanel)
            {
                ((GanttPanel)sender).DataSourceChanged(e.OldValue, e.NewValue);
            }
        }
        protected void DataSourceChanged(object oldValue, object newValue)
        {
            //if (oldValue != null)
            //{
            //    if (oldValue is INotifyPropertyChanged)
            //    {
            //        ((INotifyPropertyChanged)oldValue).PropertyChanged -= DataSourcePropertyChanged;
            //    }
            //    if (oldValue is INotifyCollectionChanged)
            //    {
            //        ((INotifyCollectionChanged)oldValue).CollectionChanged -= DataSourceCollectionChanged;
            //    }
            //}
            //if (newValue != null)
            //{
            //    if (newValue is INotifyPropertyChanged)
            //    {
            //        ((INotifyPropertyChanged)newValue).PropertyChanged += DataSourcePropertyChanged;
            //    }
            //    if (newValue is INotifyCollectionChanged)
            //    {
            //        ((INotifyCollectionChanged)newValue).CollectionChanged += DataSourceCollectionChanged;
            //    }
            //}
        }

        //protected void DataSourcePropertyChanged(object sender, PropertyChangedEventArgs e)
        //{
        //    this.Update();
        //}
        //protected void DataSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        //{
        //    this.Update();
        //}

        public DateTime StartDate
        {
            get { return (DateTime)GetValue(StartDateProperty); }
            set { SetValue(StartDateProperty, value); }
        }

        public DateTime EndDate
        {
            get { return (DateTime)GetValue(EndDateProperty); }
            set { SetValue(EndDateProperty, value); }
        }

        public double ViewPortHeight
        {
            get { return (double)GetValue(ViewPortHeightProperty); }
            set 
            {
                if (value != this.ViewPortHeight)
                {
                    SetValue(ViewPortHeightProperty, value);
                    //if (PropertyChanged != null)
                    //    PropertyChanged(this, new PropertyChangedEventArgs("ViewPortHeight"));
                }
            }
        }

        public double ViewPortWidth
        {
            get { return (double)GetValue(ViewPortWidthProperty); }
            set 
            {
                if (value != this.ViewPortWidth)
                {
                    SetValue(ViewPortWidthProperty, value);
                    //if (PropertyChanged != null)
                    //    PropertyChanged(this, new PropertyChangedEventArgs("ViewPortWidth"));
                }
            }
        }

        public double ContentHeight
        {
            get { return (double)GetValue(ContentHeightProperty); }
            set { SetValue(ContentHeightProperty, value); }
        }

        public double ContentWidth
        {
            get { return (double)GetValue(ContentWidthProperty); }
            set { SetValue(ContentWidthProperty, value); }
        }

        public double XPosition
        {
            get { return (double)GetValue(XPositionProperty); }
            set
            {
                SetValue(XPositionProperty, value);
            }
        }

        public double YPosition
        {
            get { return (double)GetValue(YPositionProperty); }
            set { SetValue(YPositionProperty, value); }
        }

        public double RowHeight
        {
            get { return (double)GetValue(RowHeightProperty); }
            set { SetValue(RowHeightProperty, value); }
        }


        public double MaxHScrollDuration
        {
            get
            {
                return (double)GetValue(MaxHScrollDurationProperty);
            }
            set
            {
                SetValue(MaxHScrollDurationProperty, value);
            }
        }


        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.TaskEntryViewer = this.GetTemplateChild("TaskEntryViewer") as TaskEntryViewer;
            this.VerticalScrollBar = this.GetTemplateChild("VerticalScrollBar") as ScrollBar;
            this.HorizontalScrollBar = this.GetTemplateChild("HorizontalScrollBar") as ScrollBar;
            SetDefaultTaskEntryViewMargin();
            MeasureHScrollBar();

            this.TaskEntryViewer.TaskRendererProvider = TaskRendererProvider;

            //RefreshHorizontalScrollBar(ContentWidth);
            this.HorizontalScrollBar.Scroll += new ScrollEventHandler(HorizontalScrollBar_Scroll);
            this.VerticalScrollBar.Scroll += new ScrollEventHandler(VerticalScrollBar_Scroll);

            this.TaskEntryLayout.ZoomChanged += new EventHandler<PropertyChangeArgsWithValue<double>>(TaskEntryLayout_ZoomChanged);
            this.TaskEntryLayout.OnLayoutUpdate += new LayoutUpdate(this.TaskEntryViewer.OnUpdate);
            this.TaskEntryLayout.OnLayoutUpdate += new LayoutUpdate(TaskEntryLayout_OnLayoutUpdate);
            this.TaskEntryLayout.BatchRowsChanged += new EventHandler(TaskEntryLayout_BatchRowsChanged);
            this.TaskEntryLayout.PropertyChanged += new PropertyChangedEventHandler(TaskEntryLayout_PropertyChanged);
        }

        void TaskEntryLayout_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals(AbstractTaskEntryLayout.VIEWPORT_HEIGHT_PROPERTY))
                ArrangeVScrollBar();
            else if (e.PropertyName.Equals(AbstractTaskEntryLayout.VIEWPORT_WIDTH_PROPERTY))
                MeasureHScrollBar();

            if (PropertyChanged != null)
            {
                PropertyChanged(this, e);
            }
        }

        void TaskEntryLayout_BatchRowsChanged(object sender, EventArgs e)
        {
            ArrangeVScrollBar();
        }

        void TaskEntryLayout_ZoomChanged(object sender, PropertyChangeArgsWithValue<double> e)
        {
            this.XPosition = (e.OldValue - e.NewValue) * this.MaxHScrollDuration + this.XPosition;
            //this.HorizontalScrollBar.Value = this.XPosition/e.NewValue;
        }

        /// <summary>
        /// do not call any where
        /// </summary>
        /// <param name="centric"></param>
        void ArrangeHScrollBar(double centric)
        {
            this.HorizontalScrollBar.Minimum = centric - MaxHScrollDuration;
            this.HorizontalScrollBar.Maximum = centric + MaxHScrollDuration;
            this.HorizontalScrollBar.Value = centric;
            this.HorizontalScrollBar.InvalidateArrange();
        }

        /// <summary>
        /// do not call it any where
        /// </summary>
        void ArrangeHScrollBar()
        {
            this.HorizontalScrollBar.Minimum = this.HorizontalScrollBar.Value - MaxHScrollDuration;
            this.HorizontalScrollBar.Maximum = this.HorizontalScrollBar.Value + MaxHScrollDuration;
            this.HorizontalScrollBar.InvalidateArrange();
        }

        void MeasureHScrollBar()
        {
            this.HorizontalScrollBar.ViewportSize = ViewPortWidth;
        }

        void HorizontalScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            double zoom = this.TaskEntryLayout.Zoom;
            double newXPostion = e.NewValue * zoom;

            //if (e.ScrollEventType == ScrollEventType.EndScroll)
            //{
            //    if (HorizontalMoveEnd != null)
            //        HorizontalMoveEnd(sender, new OnMoveEventArgs { Action = EntryAction.MoveLeft, OldValue = XPosition, NewValue = newXPostion });

            //    XPosition = newXPostion;
            //    SetDefaultTaskEntryViewMargin();
            //    this.Update();
            //}
            //else
            //{
            //    this.RaiseMoveViewToLeft(newXPostion);
            //    this.TaskEntryViewer.Margin = new Thickness(-this.MaxHScrollDuration + XPosition / zoom - e.NewValue, 0d, 0d, 0d);
            //}

            switch (e.ScrollEventType)
            {
                case ScrollEventType.LargeDecrement:
                case ScrollEventType.LargeIncrement:
                case ScrollEventType.SmallDecrement:
                case ScrollEventType.SmallIncrement:
                case ScrollEventType.EndScroll:
                    if (XPosition != newXPostion)
                    {
                        if (HorizontalMoveEnd != null)
                            HorizontalMoveEnd(sender, new OnMoveEventArgs { Action = EntryAction.MoveLeft, OldValue = XPosition, NewValue = newXPostion });

                        XPosition = newXPostion;
                        SetDefaultTaskEntryViewMargin();
                        this.Update();
                    }
                    break;
                default:
                    this.RaiseMoveViewToLeft(newXPostion);
                    this.TaskEntryViewer.Margin = new Thickness(-this.MaxHScrollDuration + XPosition / zoom - e.NewValue, 0d, 0d, 0d);
                    break;
            }
        }

        void SetDefaultTaskEntryViewMargin()
        {
            this.TaskEntryViewer.Margin = new Thickness(-this.MaxHScrollDuration, 0d, 0d, 0d);
        }

        /// <summary>
        /// 该方法可在不刷新Gantt项的状态下，移动Gantt视图
        /// 即提高了Gantt横向移动的性能，但条目显示有可能不完全，取决于当前已生成的Gantt项
        /// Remark：Gantt项指每项任务对应的单个横道图
        /// </summary>
        /// <param name="value"></param>
        internal void RaiseMoveViewToLeft(double value)
        {
            _teAction = EntryAction.MoveLeft;
            _left = value;

            if (this.HorizontalMove != null)
                this.HorizontalMove(this, new OnMoveEventArgs { Action = _teAction, NewValue = _left, OldValue=XPosition });
        }

        protected ScrollBar HorizontalScrollBar
        {
            get;
            set;
        }

        public ScrollBar VerticalScrollBar
        {
            get;
            set;
        }

        public ScrollBarVisibility VerticalScrollBarVisibility
        {
            get;
            set;
        }

        void VerticalScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            double newY = Math.Floor(e.NewValue);
            if (newY == YPosition)
                return;

            if (VerticalMove != null)
                VerticalMove(sender, new OnMoveEventArgs {  Action = EntryAction.MoveTop, NewValue=newY, OldValue=YPosition});
            
            YPosition = newY;
            this.Update();
        }

        public void Update()
        {
            this.TaskEntryLayout.Update();
        }

        void _hScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            
        }

        public TaskEntryViewer TaskEntryViewer
        {
            get;
            set;
        }

        public AbstractTaskEntryLayout TaskEntryLayout
        {
            get
            {
                return (AbstractTaskEntryLayout)GetValue(TaskEntryLayoutProperty);
            }
            set
            {
                SetValue(TaskEntryLayoutProperty, value);
            }
        }

        void ArrangeVScrollBar()
        {
            if (VScrollBarMaxinum > 0)
            {
                this.VerticalScrollBar.Maximum = VScrollBarMaxinum;
                this.VerticalScrollBar.SmallChange = 1d;
                this.VerticalScrollBar.ViewportSize = ViewPortHeight / RowHeight;
            }
            switch (VerticalScrollBarVisibility)
            {
                case ScrollBarVisibility.Hidden:
                    this.VerticalScrollBar.Visibility = Visibility.Collapsed;
                    break;
                case ScrollBarVisibility.Disabled:
                case ScrollBarVisibility.Visible:
                    this.VerticalScrollBar.Visibility = System.Windows.Visibility.Visible;
                    break;
                case ScrollBarVisibility.Auto:

                    if (VScrollBarMaxinum > 0)
                    {
                        this.VerticalScrollBar.Visibility = System.Windows.Visibility.Visible;
                    }
                    else
                    {
                        this.VerticalScrollBar.Visibility = System.Windows.Visibility.Collapsed;
                    }
                    break;

            }
        }

        private double _hsbHeight = 0d;
        protected double HScrollBarHeight
        {
            get
            {
                if (_hsbHeight == 0d)
                {
                    _hsbHeight = this.HorizontalScrollBar.ActualHeight;
                }
                return _hsbHeight;
            }
        }

        double VScrollBarMaxinum
        {
            get
            {
                return Math.Ceiling(this.TaskEntryLayout.RowCount - (ViewPortHeight - HScrollBarHeight) / RowHeight);
            }
        }

        void TaskEntryLayout_OnLayoutUpdate(object sender, LayoutUpdateEventArgs args)
        {
            ArrangeHScrollBar(this.XPosition / this.TaskEntryLayout.Zoom);
        }

        public Type TaskEntryLayoutProvider
        {
            get { return _taskEntryLayoutProvider; }
            set 
            {
                if (_taskEntryLayoutProvider != value)
                {
                    _taskEntryLayoutProvider = value;

                    BindTaskEntryLayout();
                }
            }
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            //if (_teAction == TaskEntryAction.MoveLeft)
            //{
            //    this.TaskEntryViewer.Arrange(new Rect(new Point(_left, 0d), this.TaskEntryViewer.RenderSize));
            //    return this.TaskEntryViewer.RenderSize;//base.ArrangeOverride(finalSize);
            //}
            //else
            //this.TaskEntryViewer.Arrange(new Rect(new Point(0d,0d),this.TaskEntryViewer.DesiredSize));
            return base.ArrangeOverride(finalSize);
            //return finalSize;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            //检查ViewPort是否变化，而非单独检查ViewPortHeight或者ViewPortWidth的变化
            bool viewPortChange = false;
            if (!Double.IsInfinity(availableSize.Height))
            {
                if (this.ViewPortHeight != availableSize.Height)
                {
                    this.ViewPortHeight = availableSize.Height;
                    viewPortChange = true;
                }
            }
            else
            {
                if(this.ViewPortHeight == 0d)
                {
                    this.ViewPortHeight = 400d;
                    viewPortChange = true;
                }
            }

            if (!Double.IsInfinity(availableSize.Width))
            {
                if (this.ViewPortWidth != availableSize.Width)
                {
                    this.ViewPortWidth = availableSize.Width;
                    viewPortChange = true;
                }
            }
            else
            {
                if (this.ViewPortWidth == 0d)
                {
                    this.ViewPortWidth = 300d;
                    viewPortChange = true;
                }
            }


            //ViewPort发生变化时，更新布局
            if(viewPortChange)
            {
                this.Update();
            }

            //if (this.TaskEntryViewer.EntryLayout == null)
            //{
            //    this.Update();
            //}

            Size size = new Size(ViewPortWidth,ViewPortHeight);
            this.TaskEntryViewer.Measure(size);
            return base.MeasureOverride(size);
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion


        //protected override void OnMouseWheel(MouseWheelEventArgs e)
        //{
        //    base.OnMouseWheel(e);

        //    if (Keyboard.Modifiers == ModifierKeys.Shift)
        //    {

        //        this.ContentWidth = this.ContentWidth * (e.Delta > 0 ? 0.9 : 1.1);
        //        this.Update();
        //    }
        //}
    }
}
